/* Copyright Statement:
 *
 * This software/firmware and related documentation ("AutoChips Software") are
 * protected under relevant copyright laws. The information contained herein is
 * confidential and proprietary to AutoChips Inc. and/or its licensors. Without
 * the prior written permission of AutoChips inc. and/or its licensors, any
 * reproduction, modification, use or disclosure of AutoChips Software, and
 * information contained herein, in whole or in part, shall be strictly
 * prohibited.
 *
 * AutoChips Inc. (C) 2023. All rights reserved.
 *
 * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
 * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("AUTOCHIPS SOFTWARE")
 * RECEIVED FROM AUTOCHIPS AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
 * ON AN "AS-IS" BASIS ONLY. AUTOCHIPS EXPRESSLY DISCLAIMS ANY AND ALL
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NONINFRINGEMENT. NEITHER DOES AUTOCHIPS PROVIDE ANY WARRANTY WHATSOEVER WITH
 * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
 * INCORPORATED IN, OR SUPPLIED WITH THE AUTOCHIPS SOFTWARE, AND RECEIVER AGREES
 * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
 * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
 * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN AUTOCHIPS
 * SOFTWARE. AUTOCHIPS SHALL ALSO NOT BE RESPONSIBLE FOR ANY AUTOCHIPS SOFTWARE
 * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
 * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND AUTOCHIPS'S
 * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE AUTOCHIPS SOFTWARE
 * RELEASED HEREUNDER WILL BE, AT AUTOCHIPS'S OPTION, TO REVISE OR REPLACE THE
 * AUTOCHIPS SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
 * CHARGE PAID BY RECEIVER TO AUTOCHIPS FOR SUCH AUTOCHIPS SOFTWARE AT ISSUE.
 */

/*!
 * @file ac780x_can.h
 *
 * @brief This file provides CAN integration functions interface.
 *
 */

#ifndef _AC780X_CAN_H
#define _AC780X_CAN_H

#ifdef __cplusplus
extern "C" {
#endif

/* ===========================================  Includes  =========================================== */
#include "ac7803x.h"
#include "ac780x_ckgen.h"

/* ============================================  Define  ============================================ */
/*!< CAN instance index macro */
#define CAN_INDEX(CANx)                 ((uint8_t)(((uint32_t)(CANx) - CAN0_BASE) >> 12U))

/*!< CAN filter macro */
#define CAN_MAX_FILTER_NUM              (16UL)

/*!< CAN receive fifo count */
#define CAN_RECEIVE_FIFO_COUNT          (7UL)

/*!< CAN transmit secondary buffer count (3 STB) */
#define CAN_TRANSMIT_FIFO_COUNT         (3UL)

/*!< CAN interrupt enable all interrupt macro */
#define CAN_IRQ_ALL_ENABLE_MSK          (CAN_CTRL1_EIE_Msk  | CAN_CTRL1_TSIE_Msk | CAN_CTRL1_TPIE_Msk | \
                                        CAN_CTRL1_RAFIE_Msk | CAN_CTRL1_RFIE_Msk | CAN_CTRL1_ROIE_Msk | \
                                        CAN_CTRL1_RIE_Msk   | CAN_CTRL1_EPIE_Msk | CAN_CTRL1_ALIE_Msk | CAN_CTRL1_BEIE_Msk)

/* ===========================================  Typedef  ============================================ */
/*!
 * @brief CAN work mode enumeration.
 */
typedef enum
{
    CAN_MODE_NORMAL,                                /*!< Normal mode */
    CAN_MODE_MONITOR,                               /*!< Listen only mode */
    CAN_MODE_LOOPBACK_INTERNAL,                     /*!< Loopback internal mode */
    CAN_MODE_LOOPBACK_EXTERNAL                      /*!< Loopback external mode */
} CAN_ModeType;

/*!
 * @brief CAN clock source enumeration.
 */
typedef enum
{
    CAN_CLKSRC_EXTERNAL_OSC = 0,                    /*!< Clock source from external OSC */
    CAN_CLKSRC_AHB,                                 /*!< Clock source from AHB bus */
} CAN_ClkSrcType;

/*!
 * @brief CAN message DLC enumeration.
 */
typedef enum
{
    CAN_DLC_12_BYTES = 9U,
    CAN_DLC_16_BYTES,
    CAN_DLC_20_BYTES,
    CAN_DLC_24_BYTES,
    CAN_DLC_32_BYTES,
    CAN_DLC_48_BYTES,
    CAN_DLC_64_BYTES,
} CAN_DlcType;

/*!
 * @brief CAN transmit secondary buffer status enumeration.
 */
typedef enum
{
    CAN_TSSTAT_EMPTY = 0U,                          /*!< STB is empty */
    CAN_TSSTAT_LESS_HALF,                           /*!< STB is less than or equal to half full */
    CAN_TSSTAT_MORE_HALF,                           /*!< STB is more than half full */
    CAN_TSSTAT_FULL                                 /*!< STB is full */
} CAN_TsStatusType;

/*!
 * @brief CAN receive buffer status enumeration.
 */
typedef enum
{
    CAN_RSTAT_EMPTY = 0U,                           /*!< RB is empty */
    CAN_RSTAT_LESS_ALMOST,                          /*!< > empty and < almost full */
    CAN_RSTAT_ALMOST_FULL,                          /*!< >= almost full but not full */
    CAN_RSTAT_FULL                                  /*!< RB is full */
} CAN_RbStatusType;

/*!
 * @brief CAN transmit buffer type enumeration.
 */
typedef enum
{
    CAN_TRANSMIT_PRIMARY = 0U,                      /*!< Transmit primary mode */
    CAN_TRANSMIT_SECONDARY,                         /*!< Transmit secondary mode */
} CAN_TransmitBufferType;

/*!
 * @brief CAN transmit secondary amount enumeration.
 */
typedef enum
{
    CAN_TRANSMIT_ALL = 0U,                          /*!< Transmit all message */
    CAN_TRANSMIT_ONE,                               /*!< Transmit one message */
    CAN_TRANSMIT_AMOUNT_MAX,                        /*!< Invalid transmit amount */
} CAN_TransmitAmountType;

/*!
 * @brief CAN transmit secondary mode enumeration.
 */
typedef enum
{
    CAN_TSMODE_FIFO = 0U,                           /*!< Transmit fifo mode */
    CAN_TSMODE_PRIORITY,                            /*!< Transmit priority mode */
} CAN_TransmitModeType;

/*!
 * @brief CAN receive overflow mode enumeration.
 */
typedef enum
{
    CAN_RECV_OVER_WRITE = 0U,                       /*!< Oldest message will be overwrite */
    CAN_RECV_DISCARD,                               /*!< New message will not be store */
} CAN_OverflowModeType;

/*!
 * @brief CAN time stamp position enumeration.
 */
typedef enum
{
    CAN_TIME_STAMP_SOF = 0U,                        /*!< TIME-STAMPing position SOF */
    CAN_TIME_STAMP_EOF,                             /*!< TIME-STAMPing position EOF */
} CAN_TimeStampPosType;

/*!
 * @brief CAN frame type enumeration.
 */
typedef enum
{
    CAN_CTRL_DATA_FRAME = 0U,                       /*!< Data frame */
    CAN_CTRL_REMOTE_FRAME,                          /*!< Remote frame */
} CAN_CtrlFrameType;

/*!
 * @brief CAN message information struct.
 */
typedef struct _CAN_MSG_INFO
{
    uint32_t    ID;                                /*!< CAN identifier */
    uint32_t    RTS;                               /*!< Receive time stamps */
    uint8_t     ESI;                               /*!< Transmit time-stamp enable or error state indicator */
    uint8_t     DLC;                               /*!< Data length code */
    uint8_t     BRS;                               /*!< Bit rate switch */
    uint8_t     FDF;                               /*!< FD format indicator */
    uint8_t     RTR;                               /*!< Remote transmission request */
    uint8_t     IDE;                               /*!< Identifier extension */
    uint8_t     *DATA;                             /*!< Data */
} CAN_MsgInfoType;

/*!
 * @brief CAN bit rate confige struct.
 * Bitrate = CAN_CLOCK / ((S_PRESC + 1) * (1 + (S_SEG_1 + 1) + (S_SEG_2 + 1)))
 */
typedef struct
{
    uint8_t SEG_1;                                  /*!< Bit Timing Segment 1 */
    uint8_t SEG_2;                                  /*!< Bit Timing Segment 2 */
    uint8_t SJW;                                    /*!< Synchronization Jump Width */
    uint8_t PRESC;                                  /*!< Prescaler */
} CAN_BitrateConfigType;

/*!
 * @brief CAN filter control struct.
 */
typedef struct
{
    uint8_t index;                                  /*!< Filter index */
    ACTION_Type enable;                             /*!< Enable or disable */
    uint32_t code;                                  /*!< Code data */
    uint32_t mask;                                  /*!< Mask data */
} CAN_FilterControlType;

/*!
 * @brief CAN configuration struct.
 */
typedef struct
{
    uint8_t filterNum;                              /*!< Set filter number */
    CAN_ModeType canMode;                           /*!< CAN mode */
    CAN_ClkSrcType clockSrc;                        /*!< CAN clock source */
    ACTION_Type interruptEn;                        /*!< Interrupt enable */
    CAN_TransmitModeType tsMode;                    /*!< Transmit buffer secondary operation mode */
    CAN_TransmitAmountType tsAmount;                /*!< Transmit secondary: CAN_TRANSMIT_ALL->all frames; CAN_TRANSMIT_ONE->one frame */
    ACTION_Type tpss;                               /*!< Transmission primary single shot mode for PTB */
    ACTION_Type tsss;                               /*!< Transmission secondary single shot mode for STB */
    CAN_OverflowModeType rom;                       /*!< Receive buffer overflow mode */
    uint8_t rbFullWarningLimit;                     /*!< RB buffer almost full warning limit */
    ACTION_Type selfAckEn;                          /*!< Self acknowledge enable(when LBME=1) */
    uint8_t errorWarningLimit;                      /*!< programmable error warning limit */
    ACTION_Type fdModeEn;                           /*!< FD enable */
    ACTION_Type fdIsoEn;                            /*!< FD ISO mode */
    ACTION_Type tdcEnable;                          /*!< TDC enable (when data bitrate >= 1Mbps) */
    uint8_t sspOffset;                              /*!< SSP offset */
    ACTION_Type timeStampEn;                        /*!< Time stamp enable */
    CAN_TimeClockDividerType timeStampClk;          /*!< Time stamp clock divider */
    CAN_TimeStampPosType timeStampPos;              /*!< Time stamp position  */
    ACTION_Type memEccEn;                           /*!< CAN memory ECC enable */
    ACTION_Type busOffRecDisable;                   /*!< Auto bus off recovery disable */
    uint32_t interruptMask;                         /*!< Interrupt enable mask */
    uint32_t memEccIntMask;                         /*!< CAN memory ECC interrupt enable mask */
    uint32_t waitTimes;                             /*!< Wait times in the polling mode */
    CAN_BitrateConfigType *normalBitrate;           /*!< Normal bitrate setting */
    CAN_BitrateConfigType *dataBitrate;             /*!< Data bitrate setting */
    CAN_FilterControlType *filterList;              /*!< Filter controller list */
    DeviceCallback_Type callback;                   /*!< CAN callback pointer */
} CAN_ConfigType;

/* ====================================  Functions declaration  ===================================== */
/*!
 * @brief Get CAN module base address.
 *
 * @param[in] instance: CAN module instance
 * @return CAN module base address
 */
CAN_Type* CAN_GetBase(uint8_t instance);

/*!
 * @brief Initialize CAN module.
 *
 * @param[in] CANx: CAN module
 * @param[in] config: CAN config
 * @return none
 */
uint8_t CAN_Init(CAN_Type *CANx, CAN_ConfigType *config);

/*!
 * @brief Uninitialize CAN module.
 *
 * @param[in] CANx: CAN module
 * @return none
 */
void CAN_DeInit(CAN_Type *CANx);

/*!
 * @brief Transmit CAN message.
 *
 * @param[in] CANx: CAN module
 * @param[in] info: CAN message information
 * @param[in] type: CAN transmit type
 *              - CAN_TRANSMIT_PRIMARY
 *              - CAN_TRANSMIT_SECONDARY
 * @return 0: success, -1: busy, -2: timeout, -3: send error, -4: Transmit timeout
 */
int32_t CAN_TransmitMessage(CAN_Type *CANx, const CAN_MsgInfoType *info, CAN_TransmitBufferType type);

/*!
 * @brief Set transmit amount for can secondary buffer.
 *
 * @param[in] CANx: CAN module
 * @param[in] amount: CAN transmit secondary amount
 *              - CAN_TRANSMIT_ALL
 *              - CAN_TRANSMIT_ONE
 * @return none
 */
void CAN_SetTransmitAmount(CAN_Type *CANx, CAN_TransmitAmountType amount);

/*!
 * @brief Receive CAN message.
 *
 * @param[in] CANx: CAN module
 * @param[in] info: CAN message information
 * @return 0: success, 1: no message
 */
int32_t CAN_ReceiveMessage(CAN_Type *CANx, CAN_MsgInfoType *info);

/*!
 * @brief Set CAN filter.
 *
 * @param[in] CANx: CAN module
 * @param[in] index: CAN filter index
 *              - (0-15)
 * @param[in] code: CAN filter code
 * @param[in] mask: CAN filter mask
 * @param[in] state: enable state
 *              - ENABLE
 *              - DISABLE
 * @return none
 */
void CAN_SetFilter(CAN_Type *CANx, uint8_t index, uint32_t code, uint32_t mask, ACTION_Type state);

/*!
 * @brief Wait for transmitting done in primary mode; or transmission buffer not full in secondary mode, otherwise timeout.
 *
 * @param[in] CANx: CAN module
 * @param[in] type: CAN transmit type
 *              - CAN_TRANSMIT_PRIMARY
 *              - CAN_TRANSMIT_SECONDARY
 * @return Transmit idle (flag 0: idle, 1: timeout)
 */
int32_t CAN_WaitTransmissionIdle(CAN_Type *CANx, CAN_TransmitBufferType type);

/*!
 * @brief Wait transmit done.
 *
 * @param[in] CANx: CAN module
 * @param[in] type: CAN transmit type
 *              - CAN_TRANSMIT_PRIMARY
 *              - CAN_TRANSMIT_SECONDARY
 * @return Transmit flag (0: done, 1: timeout)
 */
int32_t CAN_WaitTransmissionDone(CAN_Type *CANx, CAN_TransmitBufferType type);

/*!
 * @brief Set message information.
 *
 * @param[in] CANx: CAN module
 * @param[in] info: CAN message information
 * @param[in] type: CAN transmit type
 *              - CAN_TRANSMIT_PRIMARY
 *              - CAN_TRANSMIT_SECONDARY
 * @return none
 */
void CAN_SetMsgInfo(CAN_Type *CANx, const CAN_MsgInfoType *info, CAN_TransmitBufferType type);

/*!
 * @brief Get payload size.
 *
 * @param[in] dlcValue: DLC value
 * @return payload size
 */
uint8_t CAN_GetPayloadSize(uint8_t dlcValue);

/*!
 * @brief Get message DLC value.
 *
 * @param[in] payloadSize: payload size
 * @return DLC value
 */
uint8_t CAN_GetDlcValue(uint8_t payloadSize);

/*!
 * @brief Set call back function.
 *
 * @param[in] CANx: CAN module
 * @param[in] callbackFunc: Event call back function
 */
void CAN_SetCallBack(CAN_Type *CANx, DeviceCallback_Type callbackFunc);

/*!
 * @brief Get interrupt flags.
 *
 * @param[in] CANx: CAN module
 * @return interrupt flag
 */
uint32_t CAN_GetInterruptFlag(CAN_Type *CANx);

/*!
 * @brief Clear interrupt flags.
 *
 * @param[in] CANx: CAN module
 * @return none
 */
void CAN_ClearInterruptFlag(CAN_Type *CANx);

#ifdef __cplusplus
}
#endif

#endif /* _AC780X_CAN_H */

/* =============================================  EOF  ============================================== */
